package controleur;

import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import modele.Joueur;
import modele.Plateau;
import modele.case_.Case;
import modele.pion.Pion;
import outils.Outils;
import outils.chemin.Dijkstra;
import outils.gestionnairefichier.GestionnaireImage;
import vue.AireDeJeu;
import vue.Fenetre;
import vue.FenetreChoix;

/**
 * * L'écouteur de souris utilisé lors d'une partie
 *
 * @author nicolas
 */
public class EcouteurDeSourisJeu extends EcouteurDeSouris {

	private Pion pionSelectionne;
	private Dijkstra casesAccessibles;
	private ArrayList<Pion> pionsAttaquables;
	private ArrayList<Case> casesAttaquables;
	private boolean activeCiblesAttaqueSpeciale;

	/**
	 * Crée un écouteur de souris en fonction de l'aire qu'il observe
	 *
	 * @param aire	aire que l'écouteur va écouteur
	 * @param plateau plateau contenu dans l'aire de jeu
	 * @param j1 joueur 1
	 * @param j2 joueur 2
	 * @param f	fenetre qui contient l'aire de jeu à écouter
	 */
	public EcouteurDeSourisJeu(AireDeJeu aire, Plateau plateau, Joueur j1, Joueur j2, Fenetre f) {
		super(aire, plateau, j1, j2, f);
		activeCiblesAttaqueSpeciale = false;
	}

	@Override
	protected void clicGaucheCase(Point caseCliquee) {
		Case c = plateau.getCase(caseCliquee);
		Pion pion = c.getPion();
		// activation attaque speciale
		if (pionSelectionne != null && pion == pionSelectionne && pion.getCoupSpecial() != null && !activeCiblesAttaqueSpeciale) {
			if (pionSelectionne.getCoupSpecial().isCoupSpecialDispo()) {
				activeCiblesAttaqueSpeciale = true;
				aire.effacerZoneDeplacement();
				pionSelectionne.getCoupSpecial().setCible(c);
				aire.dessinerCoupSpecial(pionSelectionne.getCoupSpecial());
			}
		} // déselectioner pion attaque spéciale
		else if (activeCiblesAttaqueSpeciale && (pion == pionSelectionne)) {
			activeCiblesAttaqueSpeciale = false;
			pionSelectionne = null;
			aire.effacerZoneDeplacement();
		} // éffectuer attaque spéciale
		else if (pionSelectionne != null && activeCiblesAttaqueSpeciale) {
			pionSelectionne.getCoupSpecial().effectuerCoupSpecial(plateau);
			activeCiblesAttaqueSpeciale = false;
			pionSelectionne = null;
			int nbCoupsRestants = joueurCourant.getNbCoupsRestants();
			joueurCourant.setNbCoupsRestants(nbCoupsRestants - 1);
			fenetre.actualiserPanelJoueur();
			aire.effacerZoneDeplacement();
			fenetre.actualiserMiniMap();
		} // sélection d'un pion du joueur courant
		else if (pion != null && pion.getJoueur() == joueurCourant) {
			pionSelectionne = pion;
			activeCiblesAttaqueSpeciale = false;
			if (!pionSelectionne.isDeplacementEffectue()) {
				casesAccessibles = pion.getCasesAccessibles(plateau);
				aire.afficherZoneDeplacement(casesAccessibles.getCasesAccessibles().entrySet());
			} else {
				casesAccessibles = null;
				aire.effacerZoneDeplacement();
			}
			if (!pionSelectionne.isAttaqueEffectuee()) {
				pionsAttaquables = pion.getPionsAttaquables(plateau);
				casesAttaquables = pion.getCasesAttaquables(plateau);
			} else {
				pionsAttaquables = new ArrayList<Pion>();
				casesAttaquables = new ArrayList<Case>();
			}
			aire.afficherZoneAttaquable(pionsAttaquables);
			aire.afficherCaseAttaquable(casesAttaquables);
			if (pion.getCoupSpecial() != null && pion.getCoupSpecial().isCoupSpecialDispo()) {
				aire.afficherImage(GestionnaireImage.getInstance().get("src/donnees/images/Special.png"), c);
			}

		} // déplacement du pion sélectionné
		else if (pionSelectionne != null && casesAccessibles != null && casesAccessibles.getCasesAccessibles().containsKey(c)) {
			pionSelectionne.getCase().setPion(null);
			c.setPion(pionSelectionne);
			pionSelectionne.setDeplacementEffectue(true);
			int nbCoupsRestants = joueurCourant.getNbCoupsRestants();
			joueurCourant.setNbCoupsRestants(nbCoupsRestants - 1);
			fenetre.actualiserPanelJoueur();
			fenetre.actualiserMiniMap();
			aire.effacerZoneDeplacement();
			aire.afficherInfos(c.getCoord(), pionSelectionne);
			pionSelectionne = null;
		} // le pion sélectionné attaque un autre pion
		else if (pionSelectionne != null && pionsAttaquables.contains(pion) && !pionSelectionne.isAttaqueEffectuee()) {
			boolean attaqueReussie = pionSelectionne.attaque(pion);
			if (!attaqueReussie) {
				Point pt = new Point(aire.getCamera().getCoordonneesCase(pion.getCase()));
				aire.afficherMessage(pt, "Raté !", 2);
			}
			int nbCoupsRestants = joueurCourant.getNbCoupsRestants();
			joueurCourant.setNbCoupsRestants(nbCoupsRestants - 1);
			fenetre.actualiserPanelJoueur();
			aire.effacerZoneDeplacement();
			if (!pion.estDecede()) {
				aire.afficherInfos(c.getCoord(), pion);
			} else {
				fenetre.actualiserMiniMap();
			}
			aire.effacerZoneDeplacement();
			pionSelectionne = null;
			casesAccessibles = null;
		} // on clique sur une case ne contenant pas de pion
		else {
			aire.effacerZoneDeplacement();
			pionSelectionne = null;
			casesAccessibles = null;
		}


		if (!joueurCourant.peutJouer(plateau)) {
			joueurSuivant();
		}

		Joueur gagnant = plateau.getMode().getJoueurGagnant(plateau, j1, j2);
		if (gagnant != null) {
			aire.effacerZoneDeplacement();
			aire.masquerInfos();
			finPartieDialog(gagnant.getNom());
		}
	}

	@Override
	public void mouseCaseChange(MouseEvent e, Case c) {
		super.mouseCaseChange(e, c);
		if (c != null) {
			if (pionSelectionne != null) {
				aire.actualiserBuffers();
				if (casesAccessibles != null && casesAccessibles.getCasesAccessibles().containsKey(c)) {
					BufferedImage bi = GestionnaireImage.getInstance().get("src/donnees/images/Empreinte.png");
					Case c2 = null;
					ArrayList<Case> chemin = casesAccessibles.getChemin(c);
					if (chemin.size() > 1) {
						double angle = Outils.theta(chemin.get(0).getCoord(), chemin.get(1).getCoord());
						chemin.remove(0);
						for (Case c1 : chemin) {
							if (c2 != null) {
								angle = Outils.theta(c2.getCoord(), c1.getCoord());
								aire.afficherImage(bi, c2, angle);
							}
							c2 = c1;
						}
						BufferedImage bi2 = GestionnaireImage.getInstance().get("src/donnees/images/Empreinte2.png");
						aire.afficherImage(bi2, c2, angle);
					}
				} else if (c.getPion() != null && casesAttaquables.contains(c) && pionSelectionne.peutAttaquer(c.getPion())) {
					aire.afficherImage(GestionnaireImage.getInstance().get("src/donnees/images/Epee.png"), c);
				} else if (c.getPion() == pionSelectionne && c.getPion().getCoupSpecial() != null && c.getPion().getCoupSpecial().isCoupSpecialDispo()) {
					aire.afficherImage(GestionnaireImage.getInstance().get("src/donnees/images/Special.png"), c);
				}

			}

			if (activeCiblesAttaqueSpeciale) {
				aire.effacerZoneDeplacement();
				pionSelectionne.getCoupSpecial().setCible(c);
				ArrayList<Case> cases = pionSelectionne.getCoupSpecial().porteeCoupSpecial(plateau);
				aire.dessinerCoupSpecial(pionSelectionne.getCoupSpecial());
				aire.actualiserBuffers();
				for (Case cible : cases) {
					if (cible.getPion() != null) {
						aire.afficherImage(GestionnaireImage.getInstance().get("src/donnees/images/Special.png"), cible);
					}
				}
			}
		}
	}

	@Override
	public void joueurSuivant() {
		if (joueurCourant == j1) {
			joueurCourant = j2;
		} else {
			joueurCourant = j1;
		}
		fenetre.inverserPanelJoueur();
		joueurCourant.nouveauTour();
		fenetre.actualiserPanelJoueur();
		aire.effacerZoneDeplacement();

		pionSelectionne = null;
		casesAccessibles = null;
		pionsAttaquables = null;
		aire.afficherMessage(aire.getCamera().getCentre(), joueurCourant.getNom(), 2);
	}

	/**
	 *
	 * @return le pion actuellement selectionné par le joueur
	 */
	public Pion getPionSelectionne() {
		return pionSelectionne;
	}

	public void setPionSelectionne(Pion pionSelectionne) {
		this.pionSelectionne = pionSelectionne;
	}

	public void finPartieDialog(String nomGagnant) {
		Object[] options = {"Quitter", "Nouvelle Partie"};
		int n = JOptionPane.showOptionDialog(fenetre,
				"Le joueur " + nomGagnant + " a gagné !\n",
				"Fin De Partie !!",
				JOptionPane.YES_NO_OPTION,
				JOptionPane.QUESTION_MESSAGE,
				null,
				options,
				options[1]);


		final JDialog dialog = new JDialog(fenetre, "Fin Partie", true);


		dialog.setUndecorated(true);
		dialog.pack();
		dialog.setLocationRelativeTo(fenetre);

		if (n == 0) {
			// quitter
			fenetre.dispose();
		} else if (n == 1) {
			// nouvelle partie
			fenetre.dispose();
			FenetreChoix E = new FenetreChoix();
			E.setVisible(true);
		}
	}
}
